package org.gpf;

import java.util.Map;
import java.util.TreeMap;

/**
 * 字符串工具类，提供字符串的反转
 * 
 * @author gaopengfei
 * @date 2015-5-27 下午11:18:20
 */
public class StringUtil {

	private StringUtil() {

	}

	/**
	 * 将整个字符串反转
	 * 
	 * @param str
	 */
	public static String reverseString(String str) {

		return reverseString(str, 0, str.length());
	}

	/**
	 * 将字符串中的指定字串反转[start,end)
	 * 
	 * @param str
	 * @param start
	 * @param end
	 * @return
	 */
	public static String reverseString(String str, int start, int end) {

		char[] temp = str.toCharArray();
		reverseArray(temp, start, end);
//		return new String(temp);

		// 如果不用字符数组可以采用以下的算法：
		// 1. 整个字符串分为2个部分，其中只有中间的一部分是需要反转的
		// 2. 初始化一个容器（容器中包含从[0,start)的字符串）
		// 3. 从end到start将字符逐个添加到容器
		// 4. 取str的子串[end,length)添加到容器
		
		StringBuilder sb = new StringBuilder(str.substring(0, start));
		for(int i = end - 1;i >= start;i--){
			sb.append(str.charAt(i));
		}
		sb.append(str.substring(end)); 
		return sb.toString();
	}

	/**
	 * 将数组中指定下标的元素反转
	 * @param temp
	 * @param x
	 * @param y
	 */
	private static void reverseArray(char[] temp, int x, int y) {

		for (int start = x, end = y - 1; start < end; start++, end--)
			swap(temp, start, end);
	}

	/**
	 * 将数组中指定的两个值交换
	 * 
	 * @param temp
	 * @param start
	 * @param end
	 */
	private static void swap(char[] temp, int start, int end) {

		char ch = temp[start];
		temp[start] = temp[end];
		temp[end] = ch;
	}
	
	/**
	 * 获取一个字符串在另一个字符串中出现的次数。
	 * 如：aa在"aasndkfskaadkdsaakll"中出现3次
	 * 难点：如何取得下一个查找的位置
	 */
	public static int getSubStringCount(String str, String key) {

		int count = 0; // 字符串出现的次数
		int index = 0; // 查找的起始位置
		
		/*
		 * while ((index = str.indexOf(key)) != -1) { str = str.substring(index
		 * + key.length()); ++count; } return count;
		 */

		// 以下这种方式更高效
		while ((index = str.indexOf(key, index)) != -1) {
			count++;
			index = index + key.length();
		}

		return count;
	}

	/**
	 * 求两个字符串的最大相同字符串
	 * "abcwerthelloyuiodef"和"cvhellobnm"的最大相同子串是hello
	 * 思路：
	 * [0,length-0]	--->1 *
	 * [0,length-1]	--->2 **
	 * [0,length-2] --->3 ***
	 * 
	 * 在这里，假设str2是短串
	 */
	public static String getMaxCommonStr(String str1, String str2) {
		
		String max = "", min = "";

		max = str1.length() > str2.length() ? str1 : str2;
		min = max == str1 ? str2 : str1;

		for (int i = 0; i < min.length(); i++) {
			for (int j = 0, k = min.length() - i; k != min.length() + 1; j++, k++) {
				String temp = min.substring(j, k);
				System.out.println("去掉" + i + "个字符的子串：" + temp);
				if (max.contains(temp)) {
					return temp;
				}
			}
		}
		return null;
	}
	
	/**
	 * 模拟trim方法
	 * 
	 * @param str
	 * @return
	 */
	public static String myTrim(String str) {

		int start = 0, end = str.length() - 1;
		while (start < end && str.charAt(start) == ' ')
			start++;
		while (start < end && str.charAt(end) == ' ')
			end--;

		return str.substring(start, end);
	}

	/**
	 * 获取字符串中每个字符的个数
	 * 
	 * @param str输入字符串
	 * @return Map<Character, Integer>，特定字符出现的次数
	 */
	public static Map<Character, Integer> countChars(String str) {

		Map<Character, Integer> map = new TreeMap<Character, Integer>();

		char[] chs = str.toCharArray();
		int count = 0;
		for (char c : chs) {

			// 这种方式占用内存小
			Integer value = map.get(c);
			if (value != null)
				count = value;
			count++;
			map.put(c, count);
			count = 0; // 一个字符统计完成之后要清零

			/*
			 * if (!map.containsKey(c)) map.put(c, 1); else map.put(c,
			 * map.get(c) + 1);
			 */
		}
		return map;

	}

	public static void main(String[] args) {
		System.out.println(reverseString("abcde", 1, 4));
	}

}
